<template>
	<el-input ref="rengeIpt" type="text" @click="open" :placeholder="configure.placeholder" :disabled="configure.disabled"
		:value="labelVal"></el-input>

	<el-dialog v-model="visible" title="请选择" class="_framework_dialog__" append-to-body>
		<template #default>
			<RangeVue ref="rangeRef" :list="dialogList" :actived="actived" :levelLabelEnum="labelOption"
				@change="getLazyData"></RangeVue>
		</template>
		<template #footer>
			<div class="dialog-footer">
				<el-button type="primary" @click="handleChange">确认</el-button>
				<el-button @click="close">取消</el-button>
			</div>
		</template>
	</el-dialog>
</template>

<script lang="ts" setup>
import { onMounted, ref, computed, watch } from "vue";
import { NodeRangeType, PySelectGroupType, RangeListType, RangeValueType } from "./type";

import RangeVue from "./Range.vue";
import { ElInput } from "element-plus";

const props = defineProps<{
	modelValue: string;
	configure: PySelectGroupType;
}>();

const rangeRef = ref<InstanceType<typeof RangeVue> | null>(null);
const rengeIpt = ref<InstanceType<typeof ElInput> | null>(null);
/** 双向绑定 */
const inputVal = ref(props.modelValue);
/** 双向绑定 value 对应的 label */
const labelVal = ref("");
/** 回显数据 */
const actived = ref<Record<string, any>>({});
/** 控制弹窗 */
const visible = ref(false);
/** 弹窗数据 */
const dialogList = ref<RangeListType[]>([]);

const labelOption = computed(() => {
	return (
		props.configure.labelOption || {
			"0": "省",
			"1": "市",
			"2": "区",
			"3": "街",
		}
	);
});

const emits = defineEmits(["update:modelValue", "onChange"]);

//change事件
const handleChange = () => {
	visible.value = false;
	/** 处理 value 数据 */
	const rangeValue = rangeRef.value?.getValue()!;
	disposeValue(rangeValue);
	const res = getResult();
	props.configure.change && props.configure.change(inputVal.value, res);
	emits("onChange", inputVal.value);
	emits("update:modelValue", inputVal.value);
};

const getResult = () => {
	const key = props.configure.valueKeys || "value";

	switch (key) {
		case "label":
			return labelVal.value;
		case "value":
			return inputVal.value;
		case "object":
			return {
				label: labelVal.value,
				value: inputVal.value,
			};
		default:
			return inputVal.value;
	}
};

const disposeValue = (rangeValue: RangeValueType[]) => {
	const label: string[] = [];
	const value: any[] = [];

	rangeValue.forEach(item => {
		label.push(item.label);
		value.push(item.value);
	});

	labelVal.value = label.join("-");
	inputVal.value = value.join("-");
};

const pipe = (node: NodeRangeType, resolve: (value: RangeListType) => void) => {
	return (data: RangeListType) => {
		const { level } = node;
		const len = dialogList.value.length;
		if (len > level) {
			dialogList.value.splice(level + 1);
		}
		if (data.value.length) {
			dialogList.value.push(data);
		}
		resolve(data);
	};
};

/** 数据接口 */
const getLazyData = (
	item: RangeValueType = { label: "", key: "_first__", value: [] },
	level: number = -1
): Promise<RangeListType> => {
	return new Promise(resolve => {
		const { lazy } = props.configure;
		const node = { ...item, level };
		if (lazy) {
			lazy.lazyLoad(node, pipe(node, resolve));
		}
	});
};

// 回显请求
const echoView = async (newInputVal: string | Array<any>): Promise<Record<string, any>> => {
	const echoTarget: Record<string, any> = {};
	dialogList.value = [];
	return new Promise(async resolve => {
		let echoVals;
		if (Array.isArray(newInputVal)) {
			echoVals = newInputVal;
		} else {
			echoVals = newInputVal?.split("-").filter(e => e);
		}
		let result = await getLazyData();
		for (let i = 0; i < echoVals.length; i++) {
			let val = echoVals[i];
			const item = result.value?.find(el => el.value === val);
			echoTarget[i] = {
				key: item?.value,
				value: item,
			};
			result = await getLazyData(item, i);
		}
		resolve(echoTarget);
	});
};

const open = () => {
	visible.value = true;
};
const close = () => {
	visible.value = false;
};

const updateView = async () => {
	actived.value = await echoView(props.modelValue);
	const rangeVal = Object.values(actived.value)
		.filter((el: any) => el?.value)
		.map((el: any) => el.value) as RangeValueType[];
	disposeValue(rangeVal);
};

watch(
	() => props.modelValue,
	() => {
		updateView();
	}
);

onMounted(() => {
	if (props.modelValue) {
		updateView();
	} else {
		getLazyData();
	}
});
</script>

<style lang="scss">
._framework_dialog__ {
	:deep(.el-dialog__body) {
		padding: 0 15px;
	}
}

// @import "./Range.scss";
</style>
